/* Copyright (C) 2021 Rain */

/* This file is part of XNIX. */

/* 
  XNIX is free software: you can redistribute it and/or modify 
  it under the terms of the GNU General Public License as published by 
  the Free Software Foundation, either version 3 of the License, or 
  (at your option) and later version. 
*/

/*
  XNIX is distributed in the hope that it will be useful, 
  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
  GNU General Public License for more details. 
*/

/*
  You should have received a copy of the GNU General Public License 
   along with XNIX. If not, see <https://www.gnu.org/licenses/>.  
*/




#ifndef _INIT_H
#define _INIT_H

#define DEFAULT_DEBUG_LEVEL 	3
#define DEV_DEBUG_LEVEL		2
#define TEST_DEBUG_LEVEL	1


/* fastest, but no syslog and schk */

#define DEBUG_LEVEL 		DEFAULT_DEBUG_LEVEL

/* standard */

// #define DEBUG_LEVEL		DEV_DEBUG_LEVEL

/* slowest */
// #define DEBUG_LEVEL		TEST_DEBUG_LEVEL

/* how many we should put on the screen */
/* 80 characters */
#define TRACE_SYSLOG_MAX	80

#include <kernel/console.h>

#define trappoint() \
	printk(yellow, "system runs at %s:%s.%d\n", __FILE__, __FUNCTION__, __LINE__);

#define emerg(s, ...) printk(red, s, __VA_ARGS__)
#define log(s, ...)   printk(white, s, __VA_ARGS__)
#define warn(s, ...)  printk(yellow, s, __VA_ARGS__)
#define mesg(s, ...)  printk(white, s, __VA_ARGS__)


#include <kernel/types.h>
#include <kernel/errno.h>


/* that address that used to save boot.s in linux 0.01 */
/* but we use it to save syslog */
#define SYSLOG_BUFFER ((char *) 0x90000)


#define KERNEL_CS 0x0008
#define KERNEL_DS 0x0010

#define USER_CS   0x001b
#define USER_DS   0x0023


#define SEEK_SET 0x0001
#define SEEK_CUR 0x0002
#define SEEK_END 0x0003


#include <arch/io.h>

struct bootarg {
	__uint8_t bootdev;
	__uint8_t vbe_mode;
	__uint16_t vga_x;
	__uint16_t vga_y;

	/* yes, just 32 bytes this pointer is */
	__uint32_t fb_addr;

	/* cursor position x and y */
	__uint8_t x;
	__uint8_t y;

	__io_t com0, com1, com2, com3;
} __attribute__((packed));

/* init/main.c */
extern struct bootarg *bootarg;


struct inode_desc {
	/* this struct is a general descriptor, so we must know
	 * how big is it. */

	__uint32_t size;

	/* file descriptor */
	__uint32_t fd;

	/* this is optional (offset) */
	__uint32_t off;

	/* this is optional too */
	char *name;

	/* real inode saves here */
	void *real_inode;
};


struct file_opt {
	/* open a file */

#define O_EXEC 		0x00000001
#define O_RDONLY 	0x00000002
#define O_WRONLY 	0x00000004
#define O_RDWR 		(O_RDONLY | O_WRONLY)
#define O_SEARCH 	0x00000008
#define O_APPEND 	0x00000010
#define O_CREAT 	0x00000020
#define O_DIRECTORY 	0x00000040
#define O_EXCL 		0x00000080
#define O_NOCTTY 	0x00000100
#define O_NOFOLLOW 	0x00000200
#define O_NONBLOCK 	0x00000400
#define O_TRUNC 	0x00000800

	int (* open) (char *, __uint32_t, __uint32_t, errno_t *);

	/* or create one */

	/* `creat` doesn't return file-descriptor, it returns errno */
	errno_t (* creat) (char *, __uint32_t, __uint32_t);

	/* read from file-descriptor */
	errno_t (* read) (int, char *, __uint64_t);
	
	/* write to file-descriptor */
	errno_t (* write) (int, char *, __uint64_t);

	/* change position */

	/* 'seg' = whence */

	__uint32_t (* lseek) (int, __uint32_t, __uint32_t);

	/* close a file-descriptor */
	void (* close) (int);
};

struct time {
	__uint16_t year;
	__uint8_t month;
	__uint8_t day;

	__uint8_t hour;
	__uint8_t min;
	__uint8_t sec;
};


/* seconds per minutes */
#define MIN 	60
#define HOUR 	(MIN * 60)
#define DAY 	(HOUR * 24)

#define YEAR 	(DAY * 365)

#define isleapyear(year) (			\
	(((year) % 4) && (!(year) % 100)) || 	\
	((!(year) % 100) && (!(year) % 400)))


#endif

